﻿using System;
using System.Linq;
using System.Text;
using CommonManagement;
using CommonManagement.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using SmartCity.Shared;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.Validation;
using Volo.Abp.Autofac;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;

namespace CommonService.Host
{
    /// <summary>
    /// 公共服务主机模块
    /// </summary>
    [DependsOn(
        typeof(AbpAutofacModule),
        typeof(AbpAspNetCoreMvcModule),
        typeof(AbpEntityFrameworkCoreSqlServerModule),
        typeof(CommonManagementApplicationModule),
        typeof(CommonManagementHttpApiModule),
        typeof(CommonManagementEntityFrameworkCoreModule)
        )]
    public class CommonServiceHostModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = ConfigHelper.BuildConfiguration();

            // 数据库
            Configure<AbpDbContextOptions>(options =>
            {
                options.UseSqlServer();
            });

            // Swagger
            context.Services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v2.1", new OpenApiInfo { Title = "Common Service API", Version = "v2.1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            });

            // 身份认证
            var securityKey = configuration["Jwt:SecurityKey"] ?? "123456";
            var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey));
            context.Services.AddAuthentication("Bearer")
                .AddJwtBearer(o =>
                {
                    o.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = false,
                        ValidateAudience = false,
                        ValidateIssuerSigningKey = true,            // 是否验证签名
                        IssuerSigningKey = symmetricSecurityKey,    // 解密的密钥
                        ValidateLifetime = true,                    // 是否验证过期时间
                        ClockSkew = TimeSpan.Zero,                  // 过期缓冲时间
                        RequireExpirationTime = true                // 必须有过期时间
                    };
                });
            context.Services.AddScoped<IHttpContextAccessor, HttpContextAccessor>();

            // 配置跨域请求
            context.Services.AddCors(options =>
            {
                options.AddPolicy("cors", policy =>
                {
                    policy.SetIsOriginAllowed(a => true).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
                });
            });

            // 自定义过滤
            context.Services.AddMvc(options =>
            {
                var filterMetadata = options.Filters.FirstOrDefault(x => x is ServiceFilterAttribute attribute &&
                    attribute.ServiceType.Equals(typeof(AbpValidationActionFilter)));
                options.Filters.Remove(filterMetadata);
                options.Filters.Add<ValidateFilter>();
                options.Filters.Add<ExceptionFilter>();
            });

            // 启用GRPC
            context.Services.AddGrpc();
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();

            app.UseCors("cors");                // 启用跨域请求

            app.UseCorrelationId();             // 启用关联Id
            app.UseStaticFiles();               // 启用静态文件
            app.UseRouting();                   // 启用路由
            app.UseAuthentication();            // 启用认证
            app.UseAuthorization();             // 启用授权
            app.UseAbpClaimsMap();              // 启用Abp声明映射

            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v2.1/swagger.json", "Common Service API");
            });
            app.UseConfiguredEndpoints(options =>
            {
                options.MapGrpcService<RpcUserServiceRealize>();
            });

            AsyncHelper.RunSync(async () =>
            {
                using (var scope = context.ServiceProvider.CreateScope())
                {
                    await scope.ServiceProvider
                        .GetRequiredService<IDataSeeder>()
                        .SeedAsync();
                }
            });
        }
    }
}